package com.jieli.bt.att.ui.device.details

import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothProfile
import android.content.Context
import android.os.Bundle
import android.os.Parcelable
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.jieli.bt.att.R
import com.jieli.bt.att.databinding.FragmentDeviceDetailsBinding
import com.jieli.bt.att.ui.common.CommonActivity
import com.jieli.bt.att.ui.common.basic.BasicFragment
import com.jieli.bt.att.util.BluetoothUtil
import com.jieli.bt.att.util.CHexConver
import com.jieli.bt.att.util.ViewUtil

/**
 * DeviceDetailsFragment
 * @author zqjasonZhong
 * @since 2025/3/28
 * @email zhongzhuocheng@zh-jieli.com
 * @desc 设备详情界面
 */
class DeviceDetailsFragment : BasicFragment() {

    companion object {
        const val KEY_DEVICE = "device"

        fun startActivity(context: Context, device: BluetoothDevice) {
            CommonActivity.startCommonActivity(
                context, DeviceDetailsFragment::class.java.canonicalName,
                bundleOf(Pair<String, Parcelable>(KEY_DEVICE, device))
            )
        }
    }

    private lateinit var viewModel: DeviceDetailsViewModel
    private lateinit var binding: FragmentDeviceDetailsBinding

    private val logObserver = Observer<String> {
        addLog(it)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        FragmentDeviceDetailsBinding.inflate(inflater, container, false).also {
            binding = it
            return it.root
        }
    }

    @Suppress("DEPRECATION")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val device = arguments?.getParcelable(KEY_DEVICE) as BluetoothDevice?
        if (null == device) {
            finish(0)
            return
        }
        viewModel = ViewModelProvider(
            this,
            DeviceDetailsViewModel.Factory(device)
        )[DeviceDetailsViewModel::class.java]
        initUI()
        addObserver()
        viewModel.printDeviceInfo()
    }

    override fun onDestroyView() {
        viewModel.logMLD.removeObserver(logObserver)
        super.onDestroyView()
    }

    private fun initUI() {
        binding.viewTopBar.tvTitle.text = BluetoothUtil.getDeviceName(viewModel.device)
        binding.viewTopBar.btnLeft.setOnClickListener {
            finish(0)
        }
        binding.btnClearLog.setOnClickListener {
            addLog("", false)
        }
        binding.btnClearData.setOnClickListener {
            binding.etData.setText("")
            binding.etData.setSelection(0)
        }
        binding.btnSendData.setOnClickListener {
            tryToSendData()
        }
        binding.tvLogcat.isLongClickable = false
        binding.tvLogcat.movementMethod = ScrollingMovementMethod.getInstance()
    }

    private fun addObserver() {
        viewModel.btStateMLD.observe(viewLifecycleOwner) {
            if (!it) {
                finish(0)
            }
        }
        viewModel.deviceStateMLD.observe(viewLifecycleOwner) {
            if (!BluetoothUtil.deviceEquals(it.device, viewModel.device)) return@observe
            if (it.state != BluetoothProfile.STATE_CONNECTED) {
                finish(0)
            }
        }
        viewModel.logMLD.observeForever(logObserver)
    }

    private fun tryToSendData() {
        val text = binding.etData.text.toString().trim()
        if (text.isEmpty()) {
            showTips(getString(R.string.send_data_empty_tips))
            return
        }
        viewModel.sendData(CHexConver.hexStr2Bytes(text))
    }

    private fun addLog(text: String, isAppend: Boolean = true) {
        if (!isAppend) {
            binding.tvLogcat.text = text
            binding.tvLogcat.scrollTo(0, 0)
        } else {
            if (binding.tvLogcat.text.length > 4 * 1024 * 1024) {
                binding.tvLogcat.text = text
                binding.tvLogcat.scrollTo(0, 0)
            }
            binding.tvLogcat.append(text)
            binding.tvLogcat.append("\n")
            val offset: Int = ViewUtil.getTextViewHeight(binding.tvLogcat)
            if (offset > binding.tvLogcat.height) {
                binding.tvLogcat.scrollTo(0, offset - binding.tvLogcat.height)
            }
        }
    }
}